#include "Gwen/Utility.h"
#include "StompedReality/Asset/AssetManager.h"
#include "StompedReality/Asset/TextureInfo.h"
#include "StompedReality/Asset/TextureSystem.h"
#include "StompedReality/Core/Graphics/RenderSystem.h"
#include "StompedReality/Core/IGame.h"
#include "StomperLib/Gwen/GwenRenderer.h"
#include <GL/gl.h>
#include <Gwen/Texture.h>
#include <assert.h>
namespace StomperLib
{
namespace GwenBinding
{
GwenRenderer::GwenRenderer( ) : StompedReality::GameAccess( )
{
}

GwenRenderer::~GwenRenderer( )
{
}

bool GwenRenderer::intialize( ) {
  assert( this->m_Game != 0 );
  this->Init( );
  return true;
}

char* GwenRenderer::UnicodeConvert( const wchar_t* text, int len ) {
  char* out = new char[ len +1];
  wcstombs( out, text, len +1 );
  return out;
}

void GwenRenderer::Begin( )
{
  glColor4f( 1, 1, 1, 1 );
  glPushMatrix( );
  glLoadIdentity( );
}

void GwenRenderer::End( )
{
  glPopMatrix( );
  glColor4f( 1, 1, 1, 1 );
}

void GwenRenderer::SetDrawColor( Gwen::Color color )
{
  glColor4ubv( (GLubyte*)&color );
}

void GwenRenderer::DrawFilledRect( Gwen::Rect rect )
{
  Translate( rect );
  glDisable( GL_TEXTURE_2D );

//	glPushMatrix();
//	glTranslatef(-rect.w/2, -rect.h/2,0);
  glBegin( GL_QUADS );
  glVertex2i( rect.x, rect.y );
  glVertex2i( rect.x + rect.w, rect.y );
  glVertex2i( rect.x + rect.w, rect.y + rect.h );
  glVertex2i( rect.x, rect.y + rect.h );
  glEnd( );

//	glPopMatrix();
  glEnable( GL_TEXTURE_2D );
}

void GwenRenderer::StartClip( )
{
  Gwen::Rect rect = ClipRegion( );
  {
    GLint view[4];
    glGetIntegerv( GL_VIEWPORT, &view[0] );
    rect.y = view[3] - (rect.y + rect.h);
  }
  glScissor( rect.x * Scale( ), rect.y * Scale( ), rect.w * Scale( ), rect.h * Scale( ) );
  glEnable( GL_SCISSOR_TEST );
}

void GwenRenderer::EndClip( )
{
  glDisable( GL_SCISSOR_TEST );
}

void GwenRenderer::LoadTexture( Gwen::Texture* pTexture )
{
  StompedReality::Asset::TextureInfo info;
  if (!this->m_Game->getAssetManager( )->OpenTexture( info, pTexture->name.Get( ).c_str( )))
  {
    pTexture->failed = true;
  }
  pTexture->data = new int(info.glBinding);
  pTexture->width = info.width;
  pTexture->height = info.height;
}

void GwenRenderer::FreeTexture( Gwen::Texture* pTexture )
{
  GLuint* tex = (GLuint*)pTexture->data;
  if ( !tex ) return;
  glDeleteTextures( 1, tex );
  delete tex;
  pTexture->data = NULL;
}

void GwenRenderer::DrawTexturedRect( Gwen::Texture* pTexture, Gwen::Rect pTargetRect,
                                     float u1, float v1, float u2, float v2 )
{
  Translate( pTargetRect );
  glBindTexture ( GL_TEXTURE_2D, *(int*) pTexture->data );
  glColor4f( 1, 1, 1, 1 );
  glEnable( GL_TEXTURE );
  glBegin( GL_QUADS );
  glTexCoord2f( u1, v1 ); glVertex2f( pTargetRect.x, pTargetRect.y );
  glTexCoord2f( u1, v2 ); glVertex2f( pTargetRect.x, pTargetRect.y + pTargetRect.h );
  glTexCoord2f( u2, v2 ); glVertex2f( pTargetRect.x + pTargetRect.w, pTargetRect.y + pTargetRect.h );
  glTexCoord2f( u2, v1 ); glVertex2f( pTargetRect.x + pTargetRect.w, pTargetRect.y );
  glEnd( );
  glBindTexture ( GL_TEXTURE_2D, 0 );
}

Gwen::Color GwenRenderer::PixelColour( Gwen::Texture* pTexture, unsigned int x, unsigned int y,
                                       const Gwen::Color& col_default ) {
  GLuint* tex = (GLuint*)pTexture->data;
  if ( !tex ) return col_default;
  unsigned int iPixelSize = sizeof(unsigned char) * 4;
  glBindTexture( GL_TEXTURE_2D, *tex );
  unsigned char* data = (unsigned char*) malloc( iPixelSize * pTexture->width * pTexture->height );
  glGetTexImage( GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
  unsigned int iOffset = (y * pTexture->width + x) * 4;
  Gwen::Color c;
  c.r = data[0 + iOffset];
  c.g = data[1 + iOffset];
  c.b = data[2 + iOffset];
  c.a = data[3 + iOffset];
  free( data );
  return c;
}

}
}